package top.lixunda.common.validate.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import top.lixunda.common.validate.XumValid;
import top.lixunda.common.validate.core.AnnotationValidator;
import top.lixunda.common.validate.core.BaseValidatorDTO;
import top.lixunda.common.validate.core.ValidateResult;
import top.lixunda.common.validate.exception.XumValidException;

import java.lang.reflect.Parameter;

/**
 * @author Xumda
 * @version time:2019/12/9 14:54
 */
@Slf4j
public class XumValidateAspectExecutor {

    public XumValidateAspectExecutor(){
        log.info(">>>>>>>>>>>>>>>>> XumValidateAspectExecutor <<<<<<<<<<<<<<<<<<");
    }

    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        if (log.isDebugEnabled()) {
            log.debug("aop around method:{} ", proceedingJoinPoint.getSignature().getName());
        }
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Parameter[] parameters = signature.getMethod().getParameters();
        Parameter p;
        Object[] values = proceedingJoinPoint.getArgs();
        Object value;
        ValidateResult result;
        XumValid annotation;
        // 遍历方法参数是否带有XumValid注解
        for (int i = 0; i < parameters.length && i < values.length; i++) {
            p = parameters[i];
            if ((annotation = p.getAnnotation(XumValid.class)) == null) {
                continue;
            }
            // 验证参数
            log.debug("验证参数 {}  type:{}", p.getName(), p.getType().getName());
            value = values[i];
            if (BaseValidatorDTO.class.isAssignableFrom(value.getClass())) {
                log.debug("BaseEntityValidator的实现类，验证所有");
                result = ((BaseValidatorDTO) value).validateAll(annotation.value());
                log.debug("BaseValidatorDTO  result {}", result);
            } else {
                log.debug("普通实体类，只验证属性注解");
                result = new ValidateResult().addErrors(AnnotationValidator.DEFAULT_VALIDATOR.validAllField(value));
                log.debug("BaseValidatorDTO  result {} hasError {}", result, result.hasError());
            }
            if (result != null && result.hasError()) {
                log.debug("参数验证中发现错误：{}", result.getFirstError());
                throw new XumValidException(result.getFirstError());
            }
        }
        log.debug("全部验证成功");
        // AOP代理自己的代理在内层，全局异常处理在外层，不能处理异常，处理后无法在全局异常中处理，解决总是AOP异常
        return proceedingJoinPoint.proceed();
    }

}
